﻿namespace Subtitles.MydraSubtitlesSelection
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.IO;
    using System.Net;

    using MEF_Test.Bricks;
    using MEF_Test.Bricks.Subtitles;
    using MEF_Test.Contracts;
    using MEF_Test.Subtitles;

    using Microsoft.Practices.Prism.Commands;
    using Microsoft.Practices.Prism.Regions;

    /// <summary>
    /// The view model behind the view to select subtitles.
    /// </summary>
    public class SubtitlesSelectionPageViewModel : INotifyPropertyChanged, ISubtitlesSelectionPageViewModel
    {
        #region Constants and Fields

        /// <summary>
        /// The name of the <see cref="FileHandler"/> property.
        /// </summary>
        private readonly string _fileHandlerPropertyName = PropertyHelper.MemberName<SubtitlesSelectionPageViewModel>(o => o.FileHandler);

        /// <summary>
        /// The node of the media for which to find a subtitle.
        /// </summary>
        private readonly IBrowserNodeViewModel _node;

        /// <summary>
        /// The region containing the view related to this viewmodel.
        /// </summary>
        private readonly IRegion containingRegion;

        /// <summary>
        /// The name of the <see cref="ResultsPerSubtitlesProvider"/> property.
        /// </summary>
        private readonly string _resultsPerSubtitlesProviderPropertyName = PropertyHelper.MemberName<SubtitlesSelectionPageViewModel>(o => o.ResultsPerSubtitlesProvider);

        /// <summary>
        /// The backing field for the <see cref="FileHandler"/> property.
        /// </summary>
        private IFileHandler _fileHandler;

        /// <summary>
        /// The backing field for the <see cref="ResultsPerSubtitlesProvider"/>.
        /// </summary>
        private IEnumerable<SubtitlesProviderResults> _resultsPerSubtitlesProvider;

        /// <summary>
        /// A reference to the subtitlesProviders manager in charge of handling all the exported subtitles providers.
        /// </summary>
        private readonly ISubtitlesProvidersManager _subtitlesProvidersManager;

        /// <summary>
        /// A strongly typed reference of the safely casted _node's MediaHandler property.
        /// </summary>
        private IVideoMediaHandler _videoNodeMediaHandler;

        private IVideoRendererViewFactory _videoPlayerViewFactory;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="SubtitlesSelectionPageViewModel"/> class.
        /// </summary>
        /// <param name="subtitlesProvidersManager">The subtitles providers manager.</param>
        /// <param name="node">The node of the media for which to find a subtitle.</param>
        /// <param name="containingRegion">The region containing the view related to this viewmodel.</param>
        /// <param name="videoPlayerViewFactory">The video player view factory.</param>
        // FIXME : We don't need a node here : it should only be used by the view which opens the media file. Subtitles-related viewmodels shouldn't have any info about the node !
        public SubtitlesSelectionPageViewModel(ISubtitlesProvidersManager subtitlesProvidersManager, IBrowserNodeViewModel node, IRegion containingRegion, IVideoRendererViewFactory videoPlayerViewFactory)
        {
            if (subtitlesProvidersManager == null)
            {
                throw new ArgumentNullException("subtitlesProvidersManager");
            }

            if (node == null)
            {
                throw new ArgumentNullException("node");
            }
            if (containingRegion == null)
            {
                throw new ArgumentNullException("containingRegion");
            }
            if (videoPlayerViewFactory == null) throw new ArgumentNullException("videoPlayerViewFactory");
            _node = node;
            _videoPlayerViewFactory = videoPlayerViewFactory;
            this.containingRegion = containingRegion;

            if (!(this._node.MediaHandler is IVideoMediaHandler))
            {
                throw new NotSupportedException(
                    string.Format(
                        "The specified node {0} hasn't been recognized as a valid video media. Its MediaHandler (of type {1}) must implement {2}",
                        this._node,
                        this._node.MediaHandler.GetType().FullName,
                        typeof(IVideoMediaHandler).FullName));
            }
            this._videoNodeMediaHandler = (IVideoMediaHandler)this._node.MediaHandler;

            this.LoadSubtitlesCommand = new DelegateCommand<ISubtitleViewModel>(this.executeLoadSubtitlesCommand);
            this._subtitlesProvidersManager = subtitlesProvidersManager;
        }

        #endregion

        #region Events

        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the file handler.
        /// </summary>
        /// <value>The file handler.</value>
        public IFileHandler FileHandler
        {
            get
            {
                return _fileHandler;
            }

            set
            {
                if (_fileHandler != value)
                {
                    _fileHandler = value;
                    if (PropertyChanged != null)
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs(_fileHandlerPropertyName));
                    }
                }
            }
        }

        /// <summary>
        /// Occurs when the subtitle selection is validated.
        /// </summary>
        public event SubtitleSelectionValidatedHandler SubtitleSelectionValidated;

        public DelegateCommand<ISubtitleViewModel> LoadSubtitlesCommand { get; set; }

        /// <summary>
        /// Gets or sets the results per subtitles provider.
        /// </summary>
        /// <value>The results per subtitles provider.</value>
        public IEnumerable<SubtitlesProviderResults> ResultsPerSubtitlesProvider
        {
            get
            {
                return this._resultsPerSubtitlesProvider;
            }

            set
            {
                this._resultsPerSubtitlesProvider = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(_resultsPerSubtitlesProviderPropertyName));
                }
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Fetches the subtitles for the specified node.
        /// </summary>
        public void FetchSubtitles()
        {
            ResultsPerSubtitlesProvider = _subtitlesProvidersManager.GetSubtitlesAsync(_node);
        }

        #endregion

        #region Methods


        private void executeLoadSubtitlesCommand(ISubtitleViewModel selectedSubtitle)
        {
            ISubtitleHandler subtitleData = this.BuildSubtitleData(selectedSubtitle);

            var args = new SubtitleSelectionValidatedArgs(_node, subtitleData);
            if (this.SubtitleSelectionValidated != null)
            {
                this.SubtitleSelectionValidated(this, args);                
            }

            //this._videoNodeMediaHandler.Subtitles.Add(subtitleData);

            //// Todo : remove magic strings.
            //string viewName = "MydraVideoPlayerView";
            //var videoPlayerView = this.containingRegion.GetView(viewName);
            //if (videoPlayerView != null)
            //{
            //    this.containingRegion.Remove(videoPlayerView);
            //}

            ////throw new NotImplementedException("The view construction is not implemented yet : inject a factory so the current region can be replaced by the video view.");
            //var newVideoPlayerView = _videoPlayerViewFactory.Create(_videoNodeMediaHandler);
            //this.containingRegion.Add(newVideoPlayerView, viewName);
            //this.containingRegion.Activate(newVideoPlayerView);
        }

        public ISubtitleHandler BuildSubtitleData(ISubtitleViewModel selectedSubtitle)
        {
            Stream subtitle = null;
            ISubtitleHandler subtitleData;
            try
            {
                subtitle = selectedSubtitle.GetSubtitleFile();
            }
            catch (WebException e)
            {
                // TODO : define a real state for un-loadable content ?
                subtitleData = null;
            }
            finally
            {
                subtitleData = selectedSubtitle.SubtitleFormatHandler.Create(subtitle);
            }
            return subtitleData;
        }

        #endregion
    }
}